/*******************************************************************************
 *
 * DSM - Distributed Search Manager
 * Developed by Milspec Research International Pty Ltd
 * 
 * $Author: gsingh $
 * $Revision: 1.2 $
 * $Date: 2004/06/01 02:46:15 $
 *
 * (c)Copyright 2004
 *    education.au limited 
 *    DEST
 *    All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this 
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice, 
 * this list of conditions and the following disclaimer in the documentation 
 * and/or other materials provided with the distribution.
 *
 * Neither the names education.au limited, DEST nor the names of its 
 * contributors may be used to endorse or promote products derived from this 
 * software without specific prior written permission.
 *
 * To the extent permitted by law, the copyright owners of this software and 
 * its contributors:
 *
 *  (i) exclude all warranties in relation to the software; and
 * (ii) exclude liability for all losses, costs, expenses and damages arising 
 *      in any way from the use of the software whether arising from or in 
 *      relation to breach of contract, negligence or any other tort, in equity
 *      or otherwise. If the software is in breach of a warranty which is 
 *      implied by law, the copyright owners and contributors liability is
 *      limited to the replacement of the software.
 *
 *******************************************************************************
 */

package au.edu.educationau.opensource.dsm.threadpool;

/**
 * Thread Pooler for handling threads for Tasks - uses ObjectFIFO to managed
 * workers This is based on the ThreadPool written by Paul Hyde
 * 
 */
public class ThreadPool extends java.lang.Object {
	private ObjectFIFO idleWorkers;
	private ThreadPoolWorker[] workerList;

	/**
	 * Constructor
	 * 
	 * @param numberOfThreads
	 */
	public ThreadPool(int numberOfThreads) {
		// make sure that it's at least one
		numberOfThreads = Math.max(1, numberOfThreads);

		idleWorkers = new ObjectFIFO(numberOfThreads);
		workerList = new ThreadPoolWorker[numberOfThreads];

		for (int i = 0; i < workerList.length; i++) {
			workerList[i] = new ThreadPoolWorker(idleWorkers);
		}
	}

	/**
	 * executes the Runnable in the thread
	 * 
	 * @param target
	 * @exception InterruptedException
	 */
	public void execute(Runnable target) throws InterruptedException {
		// block (forever) until a worker is available
		ThreadPoolWorker worker = (ThreadPoolWorker) idleWorkers.remove();
		worker.process(target);
	}

	/** Stop Idle workers */
	public void stopRequestIdleWorkers() {
		try {
			Object[] idle = idleWorkers.removeAll();
			for (int i = 0; i < idle.length; i++) {
				((ThreadPoolWorker) idle[i]).stopRequest();
			}
		} catch (InterruptedException x) {
			Thread.currentThread().interrupt(); // re-assert
		}
	}

	/** Stop all workers */
	public void stopRequestAllWorkers() {
		// Stop the idle one's first since that won't interfere with anything
		// productive.
		stopRequestIdleWorkers();

		// give the idle workers a quick chance to die
		try {
			Thread.sleep(250);
		} catch (InterruptedException x) {
		}

		// Step through the list of ALL workers that are still alive.
		for (int i = 0; i < workerList.length; i++) {
			if (workerList[i].isAlive()) {
				workerList[i].stopRequest();
			}
		}
	}
}
